package com.biz.primus.model.promotion.vo.req;

import com.biz.primus.base.enums.order.OrderTypeEnum;
import com.biz.primus.common.utils.ValueUtils;
import com.biz.primus.model.promotion.vo.IModelPostConstructProcessor;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.*;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

/**
 * 订单促销请求详情Vo
 *
 * @author david-liu
 */
@Getter
@Setter
public class OrderPromotionReqDetailVo implements IModelPostConstructProcessor, Serializable {
    private static final long serialVersionUID = -2095219627716429365L;

    /**
     * 参数标识
     */
    @ApiModelProperty(value = "参数标识(需要传入唯一的标识符, 建议UUID)", required = true)
    private String paramSeq;

    /**
     * 当天第x单
     */
    @ApiModelProperty(value = "当天第x单", required = true)
    private Integer dayOrderNo;

    /**
     * 下单有礼活动时间范围内第x单
     */
    @ApiModelProperty(value = "下单有礼活动时间范围内第x单")
    private Integer luckyOrderTimePeriodNo;

    /**
     * 订单类型
     */
    @ApiModelProperty(value = "订单类型", allowableValues = "O2O/MALL", required = true)
    private OrderTypeEnum orderType;

    /**
     * ReqItemVo
     */
    @ApiModelProperty(value = "订单商品项明细", required = true)
    private List<OrderPromotionReqItemVo> items;

    /**
     * 所有请求的商品ID
     */
    @ApiModelProperty(hidden = true)
    @JsonIgnore
    private List<Long> requestProductIds;

    /**
     * 所有请求商品的分类ID
     */
    @ApiModelProperty(hidden = true)
    @JsonIgnore
    private Set<Long> requestCategoryIds;

    /**
     * 所有请求的商品的品牌ID
     */
    @ApiModelProperty(hidden = true)
    @JsonIgnore
    private Set<Long> requestBrandIds;

    /**
     * 请求的商品的数量表
     */
    @ApiModelProperty(hidden = true)
    @JsonIgnore
    private Map<Long, Integer> requestProductQuantities;

    /**
     * 请求的商品金额表
     */
    @ApiModelProperty(hidden = true)
    @JsonIgnore
    private Map<Long, Integer> requestProductAmount;

    /**
     * 请求的分类金额表
     */
    @ApiModelProperty(hidden = true)
    @JsonIgnore
    private Map<Long, Integer> requestCategoryAmount;

    /**
     * 请求的品牌金额表
     */
    @ApiModelProperty(hidden = true)
    @JsonIgnore
    private Map<Long, Integer> requestBrandAmount;

    /**
     * 请求中分类对应的商品ID
     */
    @ApiModelProperty(hidden = true)
    @JsonIgnore
    private Map<Long, List<Long>> requestCategoryProductIds;

    /**
     * 请求种品牌对应的商品ID
     */
    @ApiModelProperty(hidden = true)
    @JsonIgnore
    private Map<Long, List<Long>> requestBrandProductIds;

    /**
     * 是否已被触发过构后处理
     */
    private boolean hasBeenPostProcessed = false;

    /**
     * 订单商品总金额
     */
    private Integer totalAmount;

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
    }

    @Override
    public void postProcess() {
        if (!this.hasBeenPostProcessed) {
            return;
        }
        totalAmount = 0;
        if (CollectionUtils.isNotEmpty(items)) {
            if (Objects.isNull(requestProductIds)) {
                requestProductIds = Lists.newArrayList();
            } else {
                if (CollectionUtils.isNotEmpty(requestProductIds)) {
                    requestProductIds.clear();
                }
            }
            if (Objects.isNull(requestProductQuantities)) {
                requestProductQuantities = Maps.newHashMap();
            } else {
                if (MapUtils.isNotEmpty(requestProductQuantities)) {
                    requestProductQuantities.clear();
                }
            }
            if (Objects.isNull(requestCategoryAmount)) {
                requestCategoryAmount = Maps.newHashMap();
            } else {
                if (MapUtils.isNotEmpty(requestCategoryAmount)) {
                    requestCategoryAmount.clear();
                }
            }
            if (Objects.isNull(requestBrandAmount)) {
                requestBrandAmount = Maps.newHashMap();
            } else {
                if (MapUtils.isNotEmpty(requestBrandAmount)) {
                    requestBrandAmount = Maps.newHashMap();
                }
            }
            if (Objects.isNull(requestProductAmount)) {
                requestProductAmount = Maps.newHashMap();
            } else {
                if (MapUtils.isNotEmpty(requestProductAmount)) {
                    requestProductAmount.clear();
                }
            }
            if (Objects.isNull(requestCategoryIds)) {
                requestCategoryIds = Sets.newHashSet();
            } else {
                if (CollectionUtils.isNotEmpty(requestCategoryIds)) {
                    requestCategoryIds.clear();
                }
            }
            if (Objects.isNull(requestBrandIds)) {
                requestBrandIds = Sets.newHashSet();
            } else {
                if (CollectionUtils.isNotEmpty(requestBrandIds)) {
                    requestBrandIds.clear();
                }
            }
            if (Objects.isNull(requestCategoryProductIds)) {
                requestCategoryProductIds = Maps.newHashMap();
            } else {
                if (MapUtils.isNotEmpty(requestCategoryProductIds)) {
                    requestCategoryProductIds.clear();
                }
            }
            if (Objects.isNull(requestBrandProductIds)) {
                requestBrandProductIds = Maps.newHashMap();
            } else {
                if (MapUtils.isNotEmpty(requestBrandProductIds)) {
                    requestBrandProductIds.clear();
                }
            }
            items.forEach(vo -> {
                Integer productAmount = vo.getProductAmount();
                requestProductIds.add(vo.getProductId());
                requestProductQuantities.put(vo.getProductId(), vo.getQuantity());
                requestProductAmount.put(vo.getProductId(), productAmount);
                totalAmount = totalAmount + productAmount;
                if (Objects.nonNull(vo.getCategoryId())) {
                    requestCategoryIds.add(vo.getCategoryId());
                    Integer categoryAmount = requestCategoryAmount.getOrDefault(vo.getCategoryId(), 0);
                    categoryAmount = categoryAmount + productAmount;
                    requestCategoryAmount.put(vo.getCategoryId(), categoryAmount);
                    List<Long> categoryProductIds = requestCategoryProductIds.getOrDefault(vo.getCategoryId(), Lists.newArrayList());
                    categoryProductIds.add(vo.getProductId());
                    requestCategoryProductIds.put(vo.getCategoryId(), categoryProductIds);
                }
                if (Objects.nonNull(vo.getBrandId())) {
                    requestBrandIds.add(vo.getBrandId());
                    Integer brandAmount = requestBrandAmount.getOrDefault(vo.getBrandId(), 0);
                    brandAmount = brandAmount + productAmount;
                    requestBrandAmount.put(vo.getBrandId(), brandAmount);
                    List<Long> brandProductIds = requestBrandProductIds.getOrDefault(vo.getBrandId(), Lists.newArrayList());
                    brandProductIds.add(vo.getProductId());
                    requestBrandProductIds.put(vo.getBrandId(), brandProductIds);
                }
            });
            this.hasBeenPostProcessed = true;
        }
    }

    @Override
    public boolean hasBeenPostProcessed() {
        return this.hasBeenPostProcessed;
    }

    public Integer getProductAmount(Long productId) {
        return this.requestProductAmount.getOrDefault(productId, 0);
    }

    public Integer getCategoryAmount(Long categoryId) {
        return this.requestCategoryAmount.getOrDefault(categoryId, 0);
    }

    public Integer getBrandAmount(Long brandId) {
        return this.requestBrandAmount.getOrDefault(brandId, 0);
    }

    public Integer getTotalAmount() {
        return ValueUtils.getValue(totalAmount);
    }

    public List<Long> getRequestProductIds() {
        return Optional.ofNullable(this.requestProductIds).orElse(Lists.newArrayList());
    }

    public List<Long> getRequestCategoryProductIds(Long categoryId) {
        return Objects.isNull(categoryId) ? Lists.newArrayList() : requestCategoryProductIds.getOrDefault(categoryId, Lists.newArrayList());
    }

    public List<Long> getRequestBrandProductIds(Long brandId) {
        return Objects.isNull(brandId) ? Lists.newArrayList() : requestBrandProductIds.getOrDefault(brandId, Lists.newArrayList());
    }

    public Integer getRequestProductQuantity(Long productId) {
        return this.requestProductQuantities.getOrDefault(productId, 0);
    }
}
